package model.auxillary;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import model.scaling.Scaling;
import view.IObserver;

//#Neu
/**
 * A {@code  ParameterListScaling} is a container class for parameters.
 * It manages parameters of type FACILITY, FACTORY, INTERIM_RESULT_PARAMETER, 
 * FACILITY_RESULT_PARAMETER, FACTORY_RESULT_PARAMETER, 
 * LOCATION_RESULT_PARAMETER, COMPANY_RESULT_PARAMETER, and 
 * INDUSTRY_RESULT_PARAMETER and makes them accessible.
 * @author Sebastian Perlwitz
 *
 */
public class ParameterListScaling implements IObserver {

	/**
	 * A map that holds the parameter collections of this
	 * {@code ParameterListScaling}.
	 */
	private Map<ParameterType, ParameterCollectionScaling> parameterList;
	
	/**
	 * The {@code Scaling} connected to this 
	 * {@code ParameterListScaling}.
	 */
	private Scaling scaling;
	
	/**
	 * The original name of scaling connected to this 
	 * {@code ParameterListScaling}.
	 */
	private String oldScalingName;

	/**
	 * The enum class {@code ParameterType} holds all possible types of
	 * parameters.
	 * @author Sebastian Perlwitz
	 *
	 */
	public enum ParameterType {
		FACILITY_PARAMETER,
		FACTORY_PARAMETER,
		INTERIM_RESULT_PARAMETER,
		FACILITY_RESULT_PARAMETER,
		FACTORY_RESULT_PARAMETER,
		LOCATION_RESULT_PARAMETER,
		COMPANY_RESULT_PARAMETER,
		INDUSTRY_RESULT_PARAMETER,
		PRODUCT_RESULT_PARAMETER
    }
	
	/**
	 * To create a new {@code ParameterListScaling} for scalings.
	 * @param scaling the scaling that holds the parameter list to be created
	 */
	public ParameterListScaling(Scaling scaling) {
		this.scaling = scaling;
		oldScalingName = scaling.getName();
		parameterList = new HashMap<ParameterType, ParameterCollectionScaling>();
		scaling.registerObserver(this);
	}

	/**
	 * To get all parameters of same type within their collection.
	 * @param parameterType the parameter's type
	 * @return the parameters of same type
	 */
	public ParameterCollectionScaling getParameterCollection(
			ParameterType parameterType) {
		return parameterList.get(parameterType);
	}
	
	/**
	 * To get a parameter by it's unique ID.	 
	 * @param parameterKey the parameter's ID
	 * @return the parameter
	 */
	public Parameter getParameter(String parameterKey) {
		Parameter param;
		// Search in the parameters that are no tool parameters.
		for (ParameterType key : parameterList.keySet()) {
			param = getParameterCollection(key).getParameter(parameterKey);
			if (param != null) {
				return param;
			}						
		}
		return null;
	}
	
	/**
	 * To get a parameter by it's type and abbreviation.
	 * @param type the parameter's type
	 * @param paramAbbreviation the parameter's abbreviation
	 * @return the parameter
	 */
	public Parameter getParameter(
			ParameterType type, 
			String paramAbbreviation) {		
		ParameterCollectionScaling collection = parameterList.get(type);
		return collection.getParameterByAbbrev(paramAbbreviation);
	}
	
	/**
	 * Whether all parameters that have to be set by the user are set or not.
	 * @return <b>true</b> when all parameters are set
	 */
	public boolean allSet() {
		for (ParameterCollectionScaling collection : parameterList.values()) {			
			if (!collection.allSet()) {
				return false;
			}			
		}
		return true;
	}
	
	/**
	 * To add several facility parameters to this {@code ParameterListScaling}
	 * @param type the parameters' type
	 * @param paramList the parameters to be added
	 */
	public void addScalingParameters(
			ParameterType type, 
			List<Parameter> paramList) {
		ParameterCollectionScaling collection = getParameterCollection(type);
		if(collection == null) {
			collection = new ParameterCollectionScaling(
					scaling.getName(),
					createParamCollectionFacilityID(type),
					scaling.getID());
			collection.addParameters(paramList);
			parameterList.put(type, collection);
		} else {
			collection.addParameters(paramList);
		}		
	}
	
	/**
	 * To create a part description for a parameter's key.
	 * @param type the parameter's type
	 * @return the description
	 */
	private String createKeyDescription(ParameterType type) {
		switch (type) {
		case FACILITY_PARAMETER:
			return "facility";
		case FACTORY_PARAMETER:
			return "factory";
		default:
			return null;
		}
	}
	
	/**
	 * To create a name for a {@code ParameterCollectionScaling} of a scaling.
	 * @param type the collection's type
	 * @return the name
	 */
	private String createParamCollectionFacilityID(ParameterType type) {
		return "Sc_" + createKeyDescription(type) + "_"+ scaling.getID();
	}
	
	@Override
	public void update() {
		
		// When the scalings' name was changed, the description of every
		// parameter collection gets changed.
		if(!scaling.getName().equals(oldScalingName)) {
			for(ParameterType type : parameterList.keySet()) {
				ParameterCollectionScaling collection = parameterList.get(type);
				collection.setScalingName(scaling.getName());
			}
			oldScalingName = scaling.getName();
		}
	}
	
}
